package com.wlf.config;


import com.alibaba.dubbo.common.utils.StringUtils;
import com.wlf.mq.customer.UtApiListener;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.text.MessageFormat;
import java.util.concurrent.ThreadPoolExecutor;


@Configuration
public class RabbitConfig {

    @Value("${spring.rabbitmq.host}")
    private String host;

    @Value("${spring.rabbitmq.port}")
    private Integer port;

    @Value("${spring.rabbitmq.username}")
    private String username;

    @Value("${spring.rabbitmq.password}")
    private String password;

    @Value("${ut.order.queue}")
    private String utOrderQueue;

    @Value("${ut.order.exchange}")
    private String utOrderExchange;

    @Value("${ut.order.routing}")
    private String utOrderRouting;


    @Value("${ut.print.queue}")
    private String utPrintQueue;

    @Value("${ut.print.exchange}")
    private String utPrintExchange;

    @Value("${ut.print.routing}")
    private String utPrintRouting;


    @Value("${utruck.config.api.order.queue}")
    private String apiOrderQueue;

    @Value("${utruck.config.api.exchange}")
    private String apiExchange;

    @Value("${utruck.config.api.max-size}")
    private Integer maxSize;

    @Autowired
    private AmqpAdmin amqpAdmin;


    /****************************************订单队列*******************************************/
    @Bean
    public Queue OrderDirectQueue() {
        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue(utOrderQueue,true);
    }

    @Bean
    DirectExchange OrderDirectExchange() {
        return new DirectExchange(utOrderExchange,true,false);
    }
    @Bean
    Binding bindingOrderDirect() {
        return BindingBuilder.bind(OrderDirectQueue()).to(OrderDirectExchange()).with(utOrderRouting);
    }

    /****************************************打印队列*******************************************/

    @Bean
    public Queue PrintDirectQueue() {
        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue(utPrintQueue,true);
    }

    @Bean
    DirectExchange PrintDirectExchange() {
        return new DirectExchange(utPrintExchange,true,false);
    }
    @Bean
    Binding bindingPrintDirect() {
        return BindingBuilder.bind(PrintDirectQueue()).to(PrintDirectExchange()).with(utPrintRouting);
    }

    /******************************API 测试***********************************/

    /**
     * 创建订单执行队列
     * @return
     */
    @Bean
    public String[] orderQueues() {
        String[] queueNames = new String[maxSize];
        amqpAdmin.declareExchange(new DirectExchange(apiExchange));
        for (int i = 1; i <= maxSize; i++) {
            String queueName = MessageFormat.format(apiOrderQueue, i - 1 );
            queueNames[i - 1] = queueName;
            // 订单
            if (StringUtils.isNotEmpty(queueName)) {
                amqpAdmin.declareQueue(new Queue(queueName,true));
                amqpAdmin.declareBinding(new Binding(queueName,Binding.DestinationType.QUEUE,apiExchange,queueName,null));
            }
        }
        return queueNames;
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(taskConnectionFactory());
        return template;
    }


    @Bean
    @Scope("prototype")
    public UtApiListener utApiOrderBatchListener() {
        return new UtApiListener();
    }



    @Bean
    @Primary
    public ThreadPoolTaskExecutor taskExecutorBean() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(16);
        taskExecutor.setKeepAliveSeconds(300);
        taskExecutor.setMaxPoolSize(32);
        taskExecutor.setQueueCapacity(10240000);
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return taskExecutor;
    }

    @Bean(name = "connectionFactory")
    public ConnectionFactory taskConnectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setHost(host);
        connectionFactory.setPort(port);
        connectionFactory.setExecutor(taskExecutorBean());
        return connectionFactory;
    }



    /**
     *  创建执行监听器
     */
    @Bean
    public DirectMessageListenerContainer mqMessageContainer2(UtApiListener utApiListener) throws AmqpException {
        DirectMessageListenerContainer container = new DirectMessageListenerContainer(taskConnectionFactory());
        container.setQueueNames(orderQueues());
        container.setExposeListenerChannel(true);
        container.setPrefetchCount(1);// 设置每个消费者获取的最大的消息数量
        container.setConsumersPerQueue(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);// 设置确认模式为手工确认
        container.setMessageListener(utApiListener);// 监听处理类
        return container;
    }

}
